use crate::dto::{
    match_no_res_ok, match_ok,
    role::{
        SysRoleCancelUserPayload, SysRoleList, SysRoleModifyPayload, SysRolePagePayload,
        SysRoleStatusPayload, SysUserRoleCancelPayload, SysUserRolePagePayload,
    },
    user::SysUserList,
    Page, Res, ResObj,
};
use crate::service::role_service;
use hypers::prelude::*;

pub struct Role;
#[openapi(prefix = "/system", name = "/role", tag = "角色")]
impl Role {
    /// 角色列表
    #[get(
        "/list",
        parameter(
            SysRolePagePayload
        ),
        response(
            (status = 200,body=ResObj<Page<SysRoleList>>,description ="角色列表")
        ),
    )]
    async fn get_roles_by_page(payload: SysRolePagePayload) -> Res<Page<SysRoleList>> {
        match_ok::<Page<SysRoleList>>(
            role_service::get_role_by_page(
                payload.page_num.map_or(1, |v| v),
                payload.page_size.map_or(10, |v| v),
                payload.role_name,
                payload.role_key,
                payload.status,
                payload.begin_time,
                payload.end_time,
            )
            .await,
        )
    }

    /// 添加角色
    #[post(
        "/",
        response(
            (status = 200,body=ResObj<()>,description ="添加角色")
        ),
    )]
    async fn post_add_role(payload: Json<SysRoleModifyPayload>, req: &mut Request) -> Res<()> {
        let user_id = req.get::<i32>("userId").unwrap();
        let payload = payload.0;
        match_no_res_ok(
            role_service::add_role_and_bind_menu(
                user_id,
                payload.dept_check_strictly,
                payload.menu_check_strictly,
                payload.menu_ids,
                payload.role_key,
                payload.role_name,
                payload.status,
                payload.role_sort,
                payload.remark,
            )
            .await,
        )
    }

    /// 修改角色
    #[put(
        "/",
        response(
            (status = 200,body=ResObj<()>,description ="修改角色")
        ),
    )]
    async fn put_edit_role(payload: Json<SysRoleModifyPayload>, req: &mut Request) -> Res<()> {
        let user_id = req.get::<i32>("userId").unwrap();
        let payload = payload.0;
        match_no_res_ok(
            role_service::edit_role_and_bind_menu(
                user_id,
                payload.dept_check_strictly,
                payload.menu_check_strictly,
                payload.menu_ids,
                payload.role_key,
                payload.role_name,
                payload.status,
                payload.data_scope.unwrap(),
                payload.del_flag.unwrap(),
                payload.create_by.unwrap(),
                payload.create_time.unwrap(),
                payload.role_sort,
                payload.remark,
                payload.role_id.unwrap(),
            )
            .await,
        )
    }

    /// 更改角色状态
    #[put(
        "/changeStatus",
        response(
            (status = 200,body=ResObj<()>,description ="更改角色状态")
        ),
    )]
    async fn put_edit_role_status(payload: Json<SysRoleStatusPayload>) -> Res<()> {
        match_no_res_ok(
            role_service::update_role_status_by_id(payload.role_id, payload.status.clone()).await,
        )
    }

    /// 删除角色
    #[delete(
        "/:id", // OpenApi 不支持 /:id 这种路由，支持 /{id} 这种路由
        response(
            (status = 200,body=ResObj<()>,description ="删除角色")
        ),
    )]
    async fn del_role_by_id(id: Path<String>) -> Res<()> {
        match_no_res_ok(role_service::del_role_by_id(id.0).await)
    }

    /// 获取角色详情
    #[get(
        "/:id", // OpenApi 不支持 /:id 这种路由，支持 /{id} 这种路由
        response(
            (status = 200,body=ResObj<Option<SysRoleList>>,description ="获取角色详情")
        ),
    )]
    async fn get_role_by_id(id: Path<String>) -> Res<Option<SysRoleList>> {
        match_ok(role_service::get_role_by_id(id.0).await)
    }

    /// 根据角色id获取用户列表
    #[get(
        "/authUser/allocatedList",
        parameter(
            SysUserRolePagePayload
        ),
        response(
            (status = 200,body=ResObj<Page<SysUserList>>,description ="根据角色id获取用户列表")
        ),
    )]
    async fn get_users_by_role_id_page(payload: SysUserRolePagePayload) -> Res<Page<SysUserList>> {
        match_ok(
            role_service::select_users_by_role_id(
                payload.user_name,
                payload.phone_number,
                payload.role_id,
                payload.page_num.map_or(1, |v| v),
                payload.page_size.map_or(10, |v| v),
            )
            .await,
        )
    }

    /// 根据角色id获取非此角色的用户列表
    #[get(
        "/authUser/unallocatedList",
        parameter(
            SysUserRolePagePayload
        ),
        response(
            (status = 200,body=ResObj<Page<SysUserList>>,description ="根据角色id获取非此角色的用户列表")
        ),
    )]
    async fn get_users_by_not_in_role_id_page(
        payload: SysUserRolePagePayload,
    ) -> Res<Page<SysUserList>> {
        match_ok(
            role_service::select_users_not_in_role_id(
                payload.user_name,
                payload.phone_number,
                payload.role_id,
                payload.page_num.map_or(1, |v| v),
                payload.page_size.map_or(10, |v| v),
            )
            .await,
        )
    }

    /// 删除角色和用户绑定关系
    #[put(
        "/authUser/cancel",
        response(
            (status = 200,body=ResObj<()>,description ="删除角色和用户绑定关系")
        ),
    )]
    async fn del_user_role(payload: Json<SysRoleCancelUserPayload>) -> Res<()> {
        match_no_res_ok(
            role_service::del_user_role_bind(payload.user_id, payload.role_id.clone()).await,
        )
    }

    /// 删除多个角色和用户绑定关系
    #[put(
        "/authUser/cancelAll",
        parameter(
            SysUserRoleCancelPayload
        ),
        response(
            (status = 200,body=ResObj<()>,description ="删除多个角色和用户绑定关系")
        ),
    )]
    async fn del_user_role_all(payload: SysUserRoleCancelPayload) -> Res<()> {
        match_no_res_ok(
            role_service::del_user_role_bind_more(payload.user_ids.clone(), payload.role_id).await,
        )
    }

    /// 绑定多个用户和一个角色
    #[put(
        "/authUser/selectAll",
        parameter(
            SysUserRoleCancelPayload
        ),
        response(
            (status = 200,body=ResObj<()>,description ="绑定多个用户和一个角色")
        ),
    )]
    async fn put_bind_more_user_and_simple_role(payload: SysUserRoleCancelPayload) -> Res<()> {
        match_no_res_ok(
            role_service::bind_more_user_and_simple_role(payload.user_ids.clone(), payload.role_id)
                .await,
        )
    }
}
